package com.domain.threads;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

/**
 * Clase utilidad que, a traves de un solo hilo de ejecucion (ejecutor),
 * permite saber si el ejecutable que se esta corriendo actualmente en la maquina 
 * virtual es del tipo "Event dispatching thread", ejecutandolo en caso que asi sea;
 * de lo contrario, lo coloca en lista de espera para ejecutarse posteriormente.
 * @author Irving
 */
public class UtilidadSwing {

	private static final ExecutorService ejecutor = Executors.newSingleThreadExecutor(new SwingThreadFactory());

	private static volatile Thread HiloSwing;
	
	/**
	 * Retorna afirmativo en caso que el hilo en ejecucion actual sea el hiloSwing,
	 * es decir, el unico hilo capaz de actualizar la interfaz grafica
	 * @return {@link Boolean}
	 */
	public static boolean isEventDispatchThread(){
		return Thread.currentThread() == HiloSwing;
	}

	
	/**
	 * Lanza el ejecutable recibido de parametro
	 * @param task
	 */
	public static void invokeLater(Runnable task){
		ejecutor.execute(task);
	}
	
	
	/**
	 * Se registra el ejecutable, y se coloca en la cola de espera, para ser
	 * lanzado en posterioridad (mediante un ejecutable "futuro").
	 * @param task
	 * @throws InterruptedException
	 * @throws InvocationTargetException
	 */
	public static void invokeAndWait(Runnable task) throws InterruptedException, InvocationTargetException{
		Future f = ejecutor.submit(task);
		try{
			f.get();
		}catch(ExecutionException eE){
			throw new InvocationTargetException(eE);
		}
	}
	
	/**
	 * Clase interna del tipo "Fabrica" con metodo crea un nuevo Hilo a partir de un 
	 * ejecutable dado, se asigna como el hiloSwing y se retorna
	 * @author Irving
	 *
	 */
	private static class SwingThreadFactory implements ThreadFactory{
		public Thread newThread(Runnable r) {
			HiloSwing = new Thread(r);
			return HiloSwing;
		}
	}
	
}
